package gui;

import java.awt.*;
import javax.swing.JFileChooser;
import javax.swing.JPanel;
import manager.Manager;
import world.Animal;
import world.Edible;
import world.Entity;
import world.Species;

public class MainWindow extends javax.swing.JFrame 
{
    //Visualization of game board. On the board Panel.
    //When clicked calls viewObj passing indices of clicked panel
    Panel[][] pnlGrid;
    //In species panel. Shows the color of each species.
    Label[] speciesColor;
    //In species panel. Shows the name of each species.
    Label[] speciesName;
    //In species panel. Shows the population of each species.
    Label[] speciesCount;
    //The leftmost X values of spaces currently being displayed.
    int visibleX;
    //the bottommost Y values of spaces currently being displayed.
    int visibleY;
    //Opened when it’s time to add a new species
    CreateSpeciesWindow csw;
    //Opened when a species’ properties need to be changed
    EditSpeciesWindow esw;
    //Opened when starting a new sim
    NewSimWindow nsw;
    //Opened when displaying help for the user
    HelpWindow hw;
    //Opened when showing information about the program.
    AboutWindow aw;
    //Opened when an error has occured
    ErrorWindow errWin;
    //Opened when showing information about some object in the world.
    ObjDataWindow odw;
    //Reference back to manager
    Manager mgr;
    //Tells this to update once a second
    GuiThread gt;
    
    public MainWindow(Manager m, int minX, int minY) 
    {
        mgr = m;
        pnlGrid = new Panel[50][];
        visibleX = minX;
        visibleY = minY;
        initComponents();
        for(int i = 0; i < pnlGrid.length; i++)
        {
            pnlGrid[i] = new Panel[50];
            for (int j = 0; j < pnlGrid[i].length; j++)
            {
                pnlGrid[i][j] = new Panel();
                pnlGrid[i][j].setBackground(Color.WHITE);
                pnlGrid[i][j].setPreferredSize(new Dimension(5,5));
                pnlGrid[i][j].addMouseListener(new java.awt.event.MouseAdapter() 
                {
                    public void mouseClicked(java.awt.event.MouseEvent evt) 
                    {
                        //System.out.println("asdf");
                    }
                });
                GridBagConstraints gbc = new GridBagConstraints();
                gbc.gridx = i;
                gbc.gridy = j;
                gbc.fill = GridBagConstraints.BOTH;
                pnlBoard.add(pnlGrid[i][j], gbc);
            }
        }
        gt = new GuiThread(this, mgr);
        gt.start();
    }
 
    /**
     * Argument:
     * -Parent form making the call
     * Opens csw in modal form passing parent form.
     */
    void showCreateSpecies(NewSimWindow parent)
    {
        csw.setParent(parent);
        csw.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
        csw.setVisible(true);
    }
    
    /**
     * Argument:
     * -Parent form making the call
     * Opens esw in modal form passing parent form.
     */
//    void showEditSpecies(NewSimWindow parent)
//    {
//        esw.setParent(parent);
//        esw.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
//        esw.setVisible(true);
//    }
    
    /**
     * Opens the nsw in modal form.
     */
    void showNewSimWindow()
    {
        nsw.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
        nsw.setVisible(true);
    }
    
    /**
     * Argument:
     * -Location of the entity to be viewed relative to minX and minY
     * Calls getOccupantByLocation in mgr passing arguments added to 
     * their respective mins. Calls setEntity in odw passing result, 
     * then sets odw to visible.
     */
    void showObjData(int relX, int relY)
    {
        Entity seeMe = mgr.getOccupantByLocation(relX+visibleX, relY+visibleY);
        if (seeMe instanceof Animal)
        {
            odw.setEntity((Animal)seeMe, mgr);
        }
        else
        {
            odw.setEntity((Edible)seeMe, mgr);
        }
        odw.setVisible(true);
    }
    
    /**
     * Opens a file chooser for loading. Passes the resulting file to 
     * mgr’s loadSim function 
     */
//    void loadSim()
//    {
//        JFileChooser jfc = new JFileChooser();
//        jfc.showOpenDialog(this);
//        mgr.loadSim(jfc.getSelectedFile());
//    }
    
    /**
     * calls pauseUnpause() in mgr
     */
    void pauseUnpause()
    {
        btnPause.setText("unpause");
        mgr.pauseUnpause();
    }
    
    /**
     * Increments visibleY by 10 
     */
    void shiftUp()
    {
        visibleY += 10;
    }
    
    /**
     * Decrements visibleY by 10
     */
    void shiftDown()
    {
        visibleY -= 10;
    }
    
    /**
     * Increments visibleX by 10 
     */
    void shiftLeft()
    {
        visibleX += 10;
    }
    
    /**
     * Decrements visibleX by 10 
     */
    void shiftRight()
    {
        visibleX -= 10;
    }
    
    /**
     * Sets nsw to visible as modal. 
     */
    void startSim()
    {
        nsw.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
        nsw.setVisible(true);
    }
    
    /**
     * Arguments:
     * -Species list
     * -veggie spawn rate
     * -veggie content
     * -mutation factor
     * -map size
     * Passes arguments into generateSim in mgr.
     */
//    void simStarted(Species[] list, double veggieRate, int veggieCont, 
//            double mutFac, int xSize, int ySize)
//    {
//        mgr.generateSim(list, xSize, ySize, veggieRate, veggieCont, mutFac);
//    }
    
    /**
     * Opens file chooser for saving. Passes selected file to saveSim() in mgr
     */
    void saveSim()
    {
        JFileChooser jfc = new JFileChooser();
        jfc.showSaveDialog(this);
        mgr.saveSim(jfc.getSelectedFile());
    }
    
    /**
     * Arguments
     * -Trace of error
     * -Message to show with error
     * Sets ErrorWindow to visible and calls showError passing arguments
     */
    public void showException(String trace, String msg)
    {
        errWin.showError(trace, msg);
        errWin.setVisible(true);
    }
    
    /**
     * Calls exit in Manager
     */
    void exit()
    {
        gt.halt();
        mgr.exit();
    }

    /**
     * Sets hw to visible
     */
    void showHelp()
    {
        hw.setVisible(true);
    }

    /**
     * Sets aw to visible
     */
    void showAbout()
    {
        aw.setVisible(true);
    }



    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        pnlBoard = new javax.swing.JPanel();
        pnlStats = new javax.swing.JPanel();
        lblNumVeggies = new javax.swing.JLabel();
        lblNumCarcass = new javax.swing.JLabel();
        txtMutate = new javax.swing.JTextField();
        lblVeggieSpawn = new javax.swing.JLabel();
        txtVeggieSpawn = new javax.swing.JTextField();
        txtSizeX = new javax.swing.JTextField();
        txtSizeY = new javax.swing.JTextField();
        lblMutate = new javax.swing.JLabel();
        lblsizeX = new javax.swing.JLabel();
        lblSizeY = new javax.swing.JLabel();
        btnUp = new javax.swing.JButton();
        btnLeft = new javax.swing.JButton();
        btnDown = new javax.swing.JButton();
        btnRight = new javax.swing.JButton();
        btnPause = new javax.swing.JButton();
        pnlSpeciesList = new javax.swing.JPanel();
        btnNewSpecies = new javax.swing.JButton();
        mnbBar = new javax.swing.JMenuBar();
        mnuFile = new javax.swing.JMenu();
        mniNewSim = new javax.swing.JMenuItem();
        mniLoadSim = new javax.swing.JMenuItem();
        mniSave = new javax.swing.JMenuItem();
        mniExit = new javax.swing.JMenuItem();
        mnuView = new javax.swing.JMenu();
        mniObjData = new javax.swing.JMenuItem();
        mnuHelp = new javax.swing.JMenu();
        mniHowTo = new javax.swing.JMenuItem();
        mniAbout = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(new java.awt.GridBagLayout());

        pnlBoard.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pnlBoard.setMinimumSize(new java.awt.Dimension(250, 250));
        pnlBoard.setPreferredSize(new java.awt.Dimension(250, 250));
        pnlBoard.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        getContentPane().add(pnlBoard, gridBagConstraints);

        pnlStats.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        pnlStats.setLayout(new java.awt.GridBagLayout());

        lblNumVeggies.setText("Veggies on board: 0");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        pnlStats.add(lblNumVeggies, gridBagConstraints);

        lblNumCarcass.setText("Carcasses on board: 0");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        pnlStats.add(lblNumCarcass, gridBagConstraints);

        txtMutate.setEditable(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        pnlStats.add(txtMutate, gridBagConstraints);

        lblVeggieSpawn.setText("Veggie Spawn Rate:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        pnlStats.add(lblVeggieSpawn, gridBagConstraints);

        txtVeggieSpawn.setEditable(false);
        txtVeggieSpawn.setText("jTextField1");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        pnlStats.add(txtVeggieSpawn, gridBagConstraints);

        txtSizeX.setEditable(false);
        txtSizeX.setText("jTextField1");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        pnlStats.add(txtSizeX, gridBagConstraints);

        txtSizeY.setEditable(false);
        txtSizeY.setText("jTextField1");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        pnlStats.add(txtSizeY, gridBagConstraints);

        lblMutate.setText("Mutation Factor:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        pnlStats.add(lblMutate, gridBagConstraints);

        lblsizeX.setText("X axis size:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        pnlStats.add(lblsizeX, gridBagConstraints);

        lblSizeY.setText("Y axis size:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        pnlStats.add(lblSizeY, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        getContentPane().add(pnlStats, gridBagConstraints);

        btnUp.setText("^");
        btnUp.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnUpMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        getContentPane().add(btnUp, gridBagConstraints);

        btnLeft.setText("<");
        btnLeft.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnLeftMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        getContentPane().add(btnLeft, gridBagConstraints);

        btnDown.setText("v");
        btnDown.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnDownMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        getContentPane().add(btnDown, gridBagConstraints);

        btnRight.setText(">");
        btnRight.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnRightMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        getContentPane().add(btnRight, gridBagConstraints);

        btnPause.setText("Pause");
        btnPause.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                btnPauseMouseClicked(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 3;
        getContentPane().add(btnPause, gridBagConstraints);

        pnlSpeciesList.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        btnNewSpecies.setText("New Species");
        btnNewSpecies.setEnabled(false);

        javax.swing.GroupLayout pnlSpeciesListLayout = new javax.swing.GroupLayout(pnlSpeciesList);
        pnlSpeciesList.setLayout(pnlSpeciesListLayout);
        pnlSpeciesListLayout.setHorizontalGroup(
            pnlSpeciesListLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 93, Short.MAX_VALUE)
            .addGroup(pnlSpeciesListLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlSpeciesListLayout.createSequentialGroup()
                    .addGap(0, 0, Short.MAX_VALUE)
                    .addComponent(btnNewSpecies)
                    .addGap(0, 0, Short.MAX_VALUE)))
        );
        pnlSpeciesListLayout.setVerticalGroup(
            pnlSpeciesListLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 23, Short.MAX_VALUE)
            .addGroup(pnlSpeciesListLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlSpeciesListLayout.createSequentialGroup()
                    .addGap(0, 0, Short.MAX_VALUE)
                    .addComponent(btnNewSpecies)
                    .addGap(0, 0, Short.MAX_VALUE)))
        );

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 4;
        getContentPane().add(pnlSpeciesList, gridBagConstraints);

        mnuFile.setText("File");

        mniNewSim.setText("New Sim");
        mniNewSim.setEnabled(false);
        mnuFile.add(mniNewSim);

        mniLoadSim.setText("Load Sim");
        mniLoadSim.setEnabled(false);
        mnuFile.add(mniLoadSim);

        mniSave.setText("Save");
        mniSave.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mniSaveMouseClicked(evt);
            }
        });
        mnuFile.add(mniSave);

        mniExit.setText("Exit");
        mniExit.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mniExitMouseClicked(evt);
            }
        });
        mnuFile.add(mniExit);

        mnbBar.add(mnuFile);

        mnuView.setText("Edit");

        mniObjData.setText("Object Data");
        mniObjData.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mniObjDataMouseClicked(evt);
            }
        });
        mnuView.add(mniObjData);

        mnbBar.add(mnuView);

        mnuHelp.setText("Help");
        mnuHelp.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mnuHelpMouseClicked(evt);
            }
        });

        mniHowTo.setText("How To");
        mnuHelp.add(mniHowTo);

        mniAbout.setText("About");
        mniAbout.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                mniAboutMouseClicked(evt);
            }
        });
        mnuHelp.add(mniAbout);

        mnbBar.add(mnuHelp);

        setJMenuBar(mnbBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void mniSaveMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mniSaveMouseClicked
        saveSim();
    }//GEN-LAST:event_mniSaveMouseClicked

    private void mniExitMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mniExitMouseClicked
        exit();
    }//GEN-LAST:event_mniExitMouseClicked

    private void mniObjDataMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mniObjDataMouseClicked
        //viewObj(-1,-1);
    }//GEN-LAST:event_mniObjDataMouseClicked

    private void mnuHelpMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mnuHelpMouseClicked
        showHelp();
    }//GEN-LAST:event_mnuHelpMouseClicked

    private void mniAboutMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_mniAboutMouseClicked
        showAbout();
    }//GEN-LAST:event_mniAboutMouseClicked

    private void btnLeftMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnLeftMouseClicked
        shiftLeft();
    }//GEN-LAST:event_btnLeftMouseClicked

    private void btnUpMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnUpMouseClicked
        shiftUp();
    }//GEN-LAST:event_btnUpMouseClicked

    private void btnRightMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnRightMouseClicked
        shiftRight();
    }//GEN-LAST:event_btnRightMouseClicked

    private void btnDownMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnDownMouseClicked
        shiftDown();
    }//GEN-LAST:event_btnDownMouseClicked

    private void btnPauseMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_btnPauseMouseClicked
        pauseUnpause();
    }//GEN-LAST:event_btnPauseMouseClicked

    /**
     * Arguments:
     * -List of colors and what space they go on
     * Loops through argument and applies color to appropriate panels
     */
    void updateUI(GuiData gd)
    {
        SpaceColor[] sc = gd.getColors();
        for (int i = 0; i < pnlGrid.length; i++)
        {
            for (int j = 0; j < pnlGrid[i].length; j++)
            {
                pnlGrid[i][j].setBackground(Color.WHITE);
            }
        }
        
        for (int i = 0; i < sc.length; i++)
        {
//            System.out.println(i + "Red: " + sc[i].getColor().getRed());
//            System.out.println("Blue: " +sc[i].getColor().getBlue());
//            System.out.println("Green: " + sc[i].getColor().getGreen());
//            System.out.println("");
            
            
            pnlGrid[sc[i].getxOffset()][sc[i].getyOffset()].setBackground(sc[i].getColor());
//            System.out.println("(" + sc[i].getxOffset() + ", " + sc[i].getyOffset() + ") ");
//            Color c = pnlGrid[sc[i].getxOffset()][sc[i].getyOffset()].getBackground();
//            System.out.println(i + "Red: " + c.getRed());
//            System.out.println("Blue: " + c.getBlue());
//            System.out.println("Green: " + c.getGreen());
//            System.out.println("");
        }
        txtMutate.setText(String.valueOf(gd.getMutFac()));
        lblNumVeggies.setText("Veggies on board: " + gd.getNumVeg());
        lblNumCarcass.setText("Carcasses on board: " + gd.getNumCarc());
        txtVeggieSpawn.setText(String.valueOf(gd.getVeggieRate()));
        txtSizeX.setText(String.valueOf(gd.getSizeX()));
        txtSizeY.setText(String.valueOf(gd.getSizeY()));
    }


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btnDown;
    private javax.swing.JButton btnLeft;
    private javax.swing.JButton btnNewSpecies;
    private javax.swing.JButton btnPause;
    private javax.swing.JButton btnRight;
    private javax.swing.JButton btnUp;
    private javax.swing.JLabel lblMutate;
    private javax.swing.JLabel lblNumCarcass;
    private javax.swing.JLabel lblNumVeggies;
    private javax.swing.JLabel lblSizeY;
    private javax.swing.JLabel lblVeggieSpawn;
    private javax.swing.JLabel lblsizeX;
    private javax.swing.JMenuBar mnbBar;
    private javax.swing.JMenuItem mniAbout;
    private javax.swing.JMenuItem mniExit;
    private javax.swing.JMenuItem mniHowTo;
    private javax.swing.JMenuItem mniLoadSim;
    private javax.swing.JMenuItem mniNewSim;
    private javax.swing.JMenuItem mniObjData;
    private javax.swing.JMenuItem mniSave;
    private javax.swing.JMenu mnuFile;
    private javax.swing.JMenu mnuHelp;
    private javax.swing.JMenu mnuView;
    private javax.swing.JPanel pnlBoard;
    private javax.swing.JPanel pnlSpeciesList;
    private javax.swing.JPanel pnlStats;
    private javax.swing.JTextField txtMutate;
    private javax.swing.JTextField txtSizeX;
    private javax.swing.JTextField txtSizeY;
    private javax.swing.JTextField txtVeggieSpawn;
    // End of variables declaration//GEN-END:variables
}
